package com.yc.cloud.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yc.cloud.entity.HwCamera;
import com.yc.cloud.admin.dto.RecordingConfig;
import com.yc.cloud.admin.service.RecordingScheduleService;
import com.yc.cloud.admin.service.StorageStrategyResolver;
import com.yc.cloud.admin.service.SysDictService;
import com.yc.cloud.admin.service.MediaKitApiService;
import com.yc.cloud.admin.service.HwCameraService;
import com.yc.cloud.admin.dto.request.MediaKitRecordReqDTO;
import com.yc.cloud.admin.service.HwCameraRecordingLogService;
import com.yc.cloud.admin.service.SipServerService;
import com.yc.cloud.admin.vo.SipDeviceListVo;
import com.yc.cloud.admin.vo.SipDeviceVo;
import com.yc.cloud.admin.dto.request.SipDeviceQueryReqDTO;
import com.yc.cloud.api.constants.SystemConfigConstants;
import com.yc.cloud.api.enums.RecordingStatusEnum;
import com.yc.cloud.api.enums.RecordingOperationTypeEnum;
import com.yc.cloud.api.enums.RecordingResultStatusEnum;
import com.yc.cloud.common.cache.service.RedisService;
import com.yc.cloud.entity.HwCamera;
import com.yc.cloud.entity.HwCameraRecordingLog;
import com.yc.cloud.mapper.HwCameraMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import cn.hutool.core.util.StrUtil;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 录制调度服务实现类
 *
 * @author kinggu
 * @since 2025-09-17
 */
@Service
@Slf4j
public class RecordingScheduleServiceImpl implements RecordingScheduleService {

    @Resource
    private StorageStrategyResolver strategyResolver;

    @Resource
    private SysDictService sysDictService;

    @Resource
    private MediaKitApiService mediaKitApiService;

    @Resource
    private HwCameraRecordingLogService recordingLogService;

    @Resource
    private HwCameraMapper cameraMapper;

    @Resource
    private HwCameraService hwCameraService;
    
    @Resource
    private RedisService<String> redisService;

    @Resource
    private SipServerService sipServerService;

    @Override
    public void executeRecordingSchedule() {
        log.debug("开始执行录制调度任务");

        try {
            // 获取所有活跃的摄像头
            List<Long> cameraIds = getAllActiveCameraIds();
            log.info("需要检查录制状态的摄像头数量: {}", cameraIds.size());

            // 顺序处理每个摄像头（简化并发复杂度）
            for (Long cameraId : cameraIds) {
                try {
                    checkAndScheduleCamera(cameraId);
                } catch (Exception e) {
                    log.error("检查摄像头 {} 录制状态时发生异常", cameraId, e);
                    // 单个摄像头失败不影响其他摄像头的处理
                }
            }

            log.debug("录制调度任务执行完成");
        } catch (Exception e) {
            log.error("录制调度任务执行异常", e);
        }
    }

    @Override
    public void checkAndScheduleCamera(Long cameraId) {
        log.debug("开始检查摄像头 {} 的录制状态", cameraId);

        // 1. 获取当前录制配置
        RecordingConfig config = strategyResolver.getCurrentRecordingConfig(cameraId);
        
        // 2. 获取当前实际录制状态（直接从MediaKit查询）
        boolean isCurrentlyRecording = getCurrentRecordingStatus(cameraId);
        
        // 3. 判断应该录制的状态
        boolean shouldRecord = config.getShouldRecord();

        log.debug("摄像头 {} - 应该录制: {}, 当前录制中: {}, 配置来源: {}", 
            cameraId, shouldRecord, isCurrentlyRecording, 
            config.getConfigSource());

        // 4. 状态变化处理
        if (shouldRecord && !isCurrentlyRecording) {
            // 需要开始录制
            startRecording(cameraId, config);
        } else if (!shouldRecord && isCurrentlyRecording) {
            // 需要停止录制
            stopRecording(cameraId);
        } else {
            log.debug("摄像头 {} 录制状态无需变更", cameraId);
        }
    }

    @Override
    public boolean startRecording(Long cameraId, RecordingConfig config) {
        log.info("开始为摄像头 {} 启动录制", cameraId);
        
        LocalDateTime startTime = LocalDateTime.now();
        HwCameraRecordingLog logEntry = createRecordingLog(cameraId, 
            SystemConfigConstants.OPERATION_START, startTime, config);

        try {
            // 生成录制请求
            MediaKitRecordReqDTO reqDTO = buildRecordingRequest(cameraId);
            if (reqDTO == null) {
                return false;
            }
            
            // 调用MediaKit API开始录制
            boolean success = mediaKitApiService.startRecord(reqDTO);
            
            if (success) {
                // 记录成功日志
                logEntry.setResultStatus(SystemConfigConstants.RESULT_SUCCESS);
                logEntry.setExecutionDuration(System.currentTimeMillis() - 
                    startTime.atZone(java.time.ZoneId.systemDefault()).toInstant().toEpochMilli());
                
                log.info("摄像头 {} 录制启动成功", cameraId);
            } else {
                // 记录失败状态
                logEntry.setResultStatus(SystemConfigConstants.RESULT_FAILED);
                logEntry.setErrorMessage("MediaKit API调用失败");
                
                log.warn("摄像头 {} 录制启动失败", cameraId);
            }
            
            // 保存日志
            recordingLogService.save(logEntry);
            return success;
            
        } catch (Exception e) {
            log.error("摄像头 {} 启动录制时发生异常", cameraId, e);
            
            // 记录异常状态
            logEntry.setResultStatus(SystemConfigConstants.RESULT_FAILED);
            logEntry.setErrorMessage("异常: " + e.getMessage());
            recordingLogService.save(logEntry);
            
            return false;
        }
    }

    @Override
    public boolean stopRecording(Long cameraId) {
        log.info("开始为摄像头 {} 停止录制", cameraId);
        
        LocalDateTime startTime = LocalDateTime.now();
        HwCameraRecordingLog logEntry = createRecordingLog(cameraId, 
            SystemConfigConstants.OPERATION_STOP, startTime, null);

        try {
            // 生成录制请求
            MediaKitRecordReqDTO reqDTO = buildRecordingRequest(cameraId);
            if (reqDTO == null) {
                return false;
            }
            
            // 调用MediaKit API停止录制
            boolean success = mediaKitApiService.stopRecord(reqDTO);
            
            if (success) {
                // 记录成功日志
                logEntry.setResultStatus(SystemConfigConstants.RESULT_SUCCESS);
                logEntry.setExecutionDuration(System.currentTimeMillis() - 
                    startTime.atZone(java.time.ZoneId.systemDefault()).toInstant().toEpochMilli());
                
                log.info("摄像头 {} 录制停止成功", cameraId);
            } else {
                logEntry.setResultStatus(SystemConfigConstants.RESULT_FAILED);
                logEntry.setErrorMessage("MediaKit API调用失败");
                
                log.warn("摄像头 {} 录制停止失败", cameraId);
            }
            
            // 保存日志
            recordingLogService.save(logEntry);
            return success;
            
        } catch (Exception e) {
            log.error("摄像头 {} 停止录制时发生异常", cameraId, e);
            
            logEntry.setResultStatus(SystemConfigConstants.RESULT_FAILED);
            logEntry.setErrorMessage("异常: " + e.getMessage());
            recordingLogService.save(logEntry);
            
            return false;
        }
    }


    @Override
    public List<Long> getAllActiveCameraIds() {
        // 直接调用 HwCameraService 的公共方法获取在线摄像头
        return hwCameraService.getOnlineCameraIds();
    }


    /**
     * 创建录制日志记录
     */
    private HwCameraRecordingLog createRecordingLog(Long cameraId, String operationType, 
                                                   LocalDateTime operationTime, RecordingConfig config) {
        HwCameraRecordingLog log = new HwCameraRecordingLog();
        log.setCameraId(cameraId);
        log.setOperationType(operationType);
        log.setOperationTime(operationTime);
        log.setExpectedTime(operationTime); // 预期时间就是操作时间
        
        if (config != null && config.getStrategy() != null) {
            log.setStrategyId(config.getStrategy().getId());
            if (config.getTimeSlot() != null) {
                log.setTimeSlotId(config.getTimeSlot().getId());
            }
        }
        
        return log;
    }

    /**
     * 获取摄像头当前录制状态（直接从MediaKit查询）
     */
    private boolean getCurrentRecordingStatus(Long cameraId) {
        try {
            MediaKitRecordReqDTO reqDTO = buildRecordingRequest(cameraId);
            if (reqDTO == null) {
                return false;
            }
            
            // 调用MediaKit API查询录制状态
            boolean isRecording = mediaKitApiService.isRecord(reqDTO);
            log.debug("摄像头 {} 当前录制状态: {}", cameraId, isRecording);
            return isRecording;
            
        } catch (Exception e) {
            log.error("查询摄像头 {} 录制状态异常", cameraId, e);
            return false;
        }
    }

    /**
     * 构建录制请求对象
     */
    private MediaKitRecordReqDTO buildRecordingRequest(Long cameraId) {
        // 获取摄像头信息
        HwCamera camera = cameraMapper.selectById(cameraId);
        if (camera == null) {
            log.error("摄像头 {} 不存在", cameraId);
            return null;
        }
        
        // 生成stream ID: sipUsername + videoChannel
        String stream = camera.getSipUsername() + "_" + camera.getVideoChannel();
        log.debug("摄像头 {} 生成stream ID: {}", cameraId, stream);
        
        // 构建录制请求
        MediaKitRecordReqDTO reqDTO = new MediaKitRecordReqDTO();
        reqDTO.setStream(stream);
        
        return reqDTO;
    }
}